package com.itljm.cxrMarket.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itljm.cxrMarket.common.BusinessException;
import com.itljm.cxrMarket.entity.*;
import com.itljm.cxrMarket.entity.dto.HomeCountDataDTO;
import com.itljm.cxrMarket.entity.dto.MerchantRegisterDTO;
import com.itljm.cxrMarket.mapper.MerchantsMapper;
import com.itljm.cxrMarket.mapper.SysRoleMapper;
import com.itljm.cxrMarket.mapper.SysUserMapper;
import com.itljm.cxrMarket.entity.dto.UserLoginDTO;
import com.itljm.cxrMarket.mapper.SysUserRoleMapper;
import com.itljm.cxrMarket.service.SysUserService;
import com.itljm.cxrMarket.utils.JwtUtil;
import com.itljm.cxrMarket.utils.RedisUtil;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.parameters.P;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class SysUserServiceImpl implements SysUserService {

    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private MerchantsMapper merchantsMapper;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private JwtUtil jwtUtil;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public List<SysUser> selectUserPage(Page<SysUser> page, Wrapper<SysUser> entityWrapper) {
        return sysUserMapper.selectUserPage(page, entityWrapper);
    }

    @Override
    public Map<String, Object> login(SysUser user) {
        String chapter = (String) redisUtil.getCacheObject("captcha");
        if (!user.getChapter().equalsIgnoreCase(chapter)){
            throw new BusinessException("验证码有误");
        }

        try {
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
            // 认证登录，利用authenticate调用自定义实现类UserDetailsServiceImpl，
            // 根据用户名判断用户是否存在，存在则返回UserDetails，不存在则抛出异常
            Authentication authentication = authenticationManager.authenticate(authenticationToken);

            // 调用 authentication.getPrincipal() 获取认证的主体信息。
            LoginUser loginUser = (LoginUser) authentication.getPrincipal();

            String userId = loginUser.getUser().getId().toString();
            // 判断用户是否被禁用
            Integer enabled = loginUser.getUser().getEnabled();
            if (enabled != 1){
                throw new BusinessException("账户已被禁用");
            }
            // 判断用户是否新入驻的商家
            Merchants merchants = merchantsMapper.selectMerchantByUserId(Long.parseLong(userId));
            if (merchants.getCheckStatus() == 0){
                throw new BusinessException("商户信息审核中，请耐心等待");
            }else if (merchants.getCheckStatus() == 2){
                throw new BusinessException("商户信息审核未通过，请重新提交入驻信息");
            }else if (merchants.getCheckStatus() == 1){
                loginUser.getUser().setMerchantId(merchants.getMerchantId());
            }
            // 生成访问令牌
            String accessToken = jwtUtil.generateAccessToken(userId);
            // 生成刷新令牌
            String refreshToken = jwtUtil.generateRefreshToken(userId);
            // 缓存用户信息到redis中
            redisUtil.setCacheObject("user:"+userId,loginUser);

            Map<String,Object> map = new HashMap();
            map.put("AccessToken",accessToken);
            map.put("RefreshToken",refreshToken);
            map.put("User",loginUser.getUser());
            map.put("Permissions",loginUser.getPermissions());

            return map;
        }catch (AuthenticationException e){
            // 捕获认证失败异常（如 BadCredentialsException、UsernameNotFoundException）
            throw new BusinessException("用户名或密码错误");
        }

    }

    public static final String wx_appid = "wx7ee4275678464a95" ; // 小程序的appid
    public static final String wx_secret = "300368e47e134787e51b7b69b3d9cbce" ; // 小程序的密钥

    @Override
    public SysUser wxLogin(UserLoginDTO userLoginDTO) {
        // 1.调用微信接口服务，获取当前用户的openid
        String url = String.format("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
                wx_appid, wx_secret, userLoginDTO.getCode());
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet httpGet = new HttpGet(url);
            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                String responseBody = EntityUtils.toString(response.getEntity());
                // 把json格式的openid解析出来
                JSONObject jsonObject = JSON.parseObject(responseBody);
                String openid = jsonObject.getString("openid");
                // 2.判断openid是否为空
                if(openid == null){
                    return null;
                }
                // 3.判断当前用户的openid有没有在我们的数据库中，如果没有，则说明是新用户，则保存到数据库中
                SysUser user = sysUserMapper.getUserByOpenid(openid);
                redisUtil.setCacheObject("user:"+openid,user);
                if (user == null){
                    SysUser newUser = new SysUser();
                    newUser.setOpenId(openid);
                    newUser.setAvatar(userLoginDTO.getAvatarUrl());
                    newUser.setUsername("微信小程序用户");
                    newUser.setName("默认昵称");
                    newUser.setPassword(passwordEncoder.encode("123456"));
                    newUser.setPhone(userLoginDTO.getPhone());
                    newUser.setCreateTime(new Date());
                    newUser.setRoleId(3);
                    sysUserMapper.insert(newUser);
                    redisUtil.setCacheObject("user:"+openid,newUser);
                    return newUser;
                }

                return user;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public String getPhoneNumber(String code) {
        // 配置请求超时等
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(5000)
                .setSocketTimeout(5000)
                .build();

        // 在方法级别创建一个 HttpClient 实例，并在方法结束时关闭
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {

            String accessToken = null; // 用于存储获取到的 access_token

            // --- 第一步：获取 access_token ---
            String tokenUrl = "https://api.weixin.qq.com/cgi-bin/stable_token";
            HttpPost tokenHttpPost = new HttpPost(tokenUrl);
            tokenHttpPost.setConfig(requestConfig);

            JSONObject tokenReqJson = new JSONObject();
            tokenReqJson.put("grant_type", "client_credential");
            tokenReqJson.put("appid", wx_appid);
            tokenReqJson.put("secret", wx_secret);
            tokenReqJson.put("force_refresh", false); // 根据需要设置是否强制刷新

            StringEntity tokenRequestEntity = new StringEntity(
                    tokenReqJson.toJSONString(),
                    ContentType.APPLICATION_JSON
            );
            tokenRequestEntity.setContentEncoding("UTF-8");
            tokenHttpPost.setEntity(tokenRequestEntity);

            // 执行获取 token 请求，并确保响应关闭
            try (CloseableHttpResponse tokenResponse = httpClient.execute(tokenHttpPost)) {
                int tokenStatusCode = tokenResponse.getStatusLine().getStatusCode();
                HttpEntity tokenResponseEntity = tokenResponse.getEntity();

                if (tokenResponseEntity == null) {
                    throw new IOException("获取 access_token 响应体为空");
                }

                String tokenResponseBody = EntityUtils.toString(tokenResponseEntity, StandardCharsets.UTF_8);
                System.out.println("获取access_token的响应：" + tokenResponseBody);

                if (tokenStatusCode != 200) {
                    throw new IOException("获取 access_token 接口请求失败，HTTP 状态码: " + tokenStatusCode + ", 响应: " + tokenResponseBody);
                }

                JSONObject tokenJsonResponse = JSON.parseObject(tokenResponseBody);

                if (tokenJsonResponse.containsKey("errcode") && tokenJsonResponse.getIntValue("errcode") != 0) {
                    int errcode = tokenJsonResponse.getIntValue("errcode");
                    String errmsg = tokenJsonResponse.getString("errmsg");
                    throw new IOException("微信接口返回错误（获取 token），错误码: " + errcode + ", 错误信息: " + errmsg);
                }

                accessToken = tokenJsonResponse.getString("access_token");
                System.out.println("解析出来的access_token：" + accessToken);

            } // tokenResponse 会在这里自动关闭

            if (accessToken == null) {
                throw new IOException("未能成功获取 access_token"); // 逻辑上确保 token 不为 null

            }

            // --- 第二步：使用 access_token 获取手机号码 ---
            String getNumUrl = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken;
            HttpPost getNumHttpPost = new HttpPost(getNumUrl);
            getNumHttpPost.setConfig(requestConfig);

            JSONObject getNumReqJson = new JSONObject();
            getNumReqJson.put("code", code); // 前端传来的 code

            StringEntity getNumRequestEntity = new StringEntity(
                    getNumReqJson.toJSONString(),
                    ContentType.APPLICATION_JSON // 正确设置 Content-Type
            );
            getNumRequestEntity.setContentEncoding("UTF-8"); // 正确设置编码
            getNumHttpPost.setEntity(getNumRequestEntity);

            // 执行获取手机号请求，并确保响应关闭
            try (CloseableHttpResponse getNumResponse = httpClient.execute(getNumHttpPost)) {
                int getNumStatusCode = getNumResponse.getStatusLine().getStatusCode();
                HttpEntity getNumResponseEntity = getNumResponse.getEntity();

                if (getNumResponseEntity == null) {
                    throw new IOException("获取手机号响应体为空");
                }

                String getNumResponseBody = EntityUtils.toString(getNumResponseEntity, StandardCharsets.UTF_8);
                System.out.println("获取手机号码的响应：" + getNumResponseBody);

                if (getNumStatusCode != 200) {
                    throw new IOException("获取手机号接口请求失败，HTTP 状态码: " + getNumStatusCode + ", 响应: " + getNumResponseBody);
                }

                JSONObject getNumJsonResponse = JSON.parseObject(getNumResponseBody);

                if (getNumJsonResponse.containsKey("errcode") && getNumJsonResponse.getIntValue("errcode") != 0) {
                    int errcode = getNumJsonResponse.getIntValue("errcode");
                    String errmsg = getNumJsonResponse.getString("errmsg");
                    // 针对 40029 等常见错误做提示
                    if (errcode == 40029) {
                        throw new IOException("微信接口返回错误（获取手机号）：code 无效/已使用/已过期。错误码: " + errcode + ", 错误信息: " + errmsg);
                    } else {
                        throw new IOException("微信接口返回错误（获取手机号），错误码: " + errcode + ", 错误信息: " + errmsg);
                    }
                }

                // 成功时提取手机号
                if (getNumJsonResponse.containsKey("phone_info") && getNumJsonResponse.getJSONObject("phone_info").containsKey("phoneNumber")) {
                    String phoneNumber = getNumJsonResponse.getJSONObject("phone_info").getString("phoneNumber");
                    System.out.println("当前登录用户的手机号码为："+ phoneNumber);
                    return phoneNumber; // 返回解析出的手机号
                } else {
                    throw new IOException("获取手机号响应格式不正确或未包含手机号信息: " + getNumResponseBody);
                }
            }

        } // httpClient 会在这里自动关闭 (在方法结束或异常时)
        catch (IOException e) {
            // 捕获并重新抛出 IO 异常，可以在调用方法处捕获并处理
            System.err.println("获取手机号过程中发生 IO 错误: " + e.getMessage());
        } catch (Exception e) {
            // 捕获其他可能的异常，如 JSON 解析错误等
            System.err.println("获取手机号过程中发生未知错误: " + e.getMessage());
        }
        return null; // 如果发生异常，确保返回 null 以避免潜在问题
    }

    @Override
    public SysUser selectByUserName(String userName) {
        return sysUserMapper.selectOne(new QueryWrapper<SysUser>().eq("username", userName));
    }

    @Override
    public SysUser selectById(Long id) {
        SysUser sysUser = sysUserMapper.selectUserById(id);
        return sysUser;
    }

    @Override
    public SysUser selectIdByName(String name) {
        return sysUserMapper.selectOne(new QueryWrapper<SysUser>().eq("name", name));
    }

    @Override
    public boolean updateById(SysUser sysUser) {
        return sysUserMapper.updateById(sysUser) > 0;
    }

    @Override
    public boolean insert(SysUser sysUser) {
        return sysUserMapper.insert(sysUser) > 0;
    }

    @Override
    public int deleteBatch(Long[] ids) {
        if (ids == null || ids.length == 0) {
            return 0;
        }
        return sysUserMapper.deleteBatchIds(Arrays.asList(ids));
    }

    @Override
    public boolean updatePassword(SysUser sysUser) {
        sysUser.setPassword(passwordEncoder.encode(sysUser.getPassword()));
        return sysUserMapper.updateById(sysUser) > 0;
    }

    @Override
    public boolean register(MerchantRegisterDTO entity) {
        SysUser user = sysUserMapper.selectOne(new QueryWrapper<SysUser>().eq("username", entity.getUsername()));
        Merchants m1 = merchantsMapper.selectMerchantByUserId(user.getId());
        if (user != null && m1.getCheckStatus() == 1) {// 用户已存在，并且商户审核通过，则不允许重复注册
            return false;
        }else if (user != null && m1.getCheckStatus() == 2) { // 用户已存在，并且商户审核不通过，则允许重新注册
            user.setUsername(entity.getUsername());
            user.setPhone(entity.getPhone());
            user.setPassword(passwordEncoder.encode(entity.getPassword()));
            user.setEmail(entity.getEmail());
            user.setUpdateTime(new Date());
            user.setEnabled(1);
            int insertU = sysUserMapper.updateById(user);

            m1.setUserId(user.getId());
            m1.setMerchantBoss(entity.getMerchantBoss());
            m1.setMerchantName(entity.getShopName());
            m1.setAddress(entity.getShopAddress());
            m1.setBusinessLicense(entity.getBusinessLicense());
            m1.setContactPhone(entity.getPhone());
            m1.setMerchantStatus(0);
            m1.setCheckStatus(0); // 审核状态，0为待审核，1为审核通过，2为审核不通过
            int insertM = merchantsMapper.updateById(m1);
            return insertU + insertM == 2;
        }else {
            SysUser sysUser = new SysUser();
            sysUser.setUsername(entity.getUsername());
            sysUser.setPhone(entity.getPhone());
            sysUser.setPassword(passwordEncoder.encode(entity.getPassword()));
            sysUser.setEmail(entity.getEmail());
            sysUser.setCreateTime(new Date());
            sysUser.setEnabled(1);
            int insertU = sysUserMapper.insert(sysUser);
            sysUserRoleMapper.insertUserRole(sysUser.getId(), 2L);// 商户角色
            Merchants merchants = new Merchants();
            merchants.setUserId(sysUser.getId());
            merchants.setMerchantBoss(entity.getMerchantBoss());
            merchants.setMerchantName(entity.getShopName());
            merchants.setAddress(entity.getShopAddress());
            merchants.setBusinessLicense(entity.getBusinessLicense());
            merchants.setContactPhone(entity.getPhone());
            merchants.setMerchantStatus(0);
            merchants.setCheckStatus(0); // 审核状态，0为待审核，1为审核通过，2为审核不通过
            int insertM = merchantsMapper.insert(merchants);
            return insertU + insertM == 2;
        }
    }

    @Override
    public HomeCountDataDTO getHomeCountData() {
        return sysUserMapper.getHomeCountData();
    }

    @Override
    public boolean deleteById(Long id) {
        return sysUserMapper.deleteById(id) > 0;
    }

}
